package com.bw.xiaosy.redis;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

/**
 * @author Xiaosy
 * @date 2017-03-30 17:07
 */
@Service
public class RedisSessionDao extends AbstractSessionDAO {

    private static Logger logger = LoggerFactory.getLogger(RedisSessionDao.class);
    @Autowired
    private RedisManager redisManager;
    @Autowired
    private RedisConfiguration conf;
    /**
     * The Redis key prefix for the sessions
     */
    private String keyPrefix = "shiro_redis_session:";


    private void saveSession(Session session)
    {
        if(session == null || session.getId() == null)
        {
            logger.error("session or session id is null");
            return;
        }
        byte[]key = getByteKey(session.getId());
        byte[]value = SerializeUtils.serialize(session);
        session.setTimeout(conf.getTimeout() * 1000);
        redisManager.set(key,value,conf.getExpire());
    }

    @Override
    protected Serializable doCreate(Session session) {
        Serializable sessionId = this.generateSessionId(session);
        this.assignSessionId(session,sessionId);
        this.saveSession(session);
        return sessionId;
    }

    @Override
    protected Session doReadSession(Serializable serializable) {
        if(serializable == null)
        {
            logger.error("session id is null");
            return  null;
        }
        Session session = (Session) SerializeUtils.deserialize(redisManager.get(getByteKey(serializable)));
        return session;
    }

    @Override
    public void update(Session session) throws UnknownSessionException {
        this.saveSession(session);
    }

    @Override
    public void delete(Session session) {
        if(session == null || session.getId() == null){
            logger.error("session or session id is null");
            return;
        }
        redisManager.del(getByteKey(session.getId()));
    }

    @Override
    public Collection<Session> getActiveSessions() {
        Set<Session> sessions = new HashSet<>();
        Set<byte[]> keys = redisManager.keys(this.keyPrefix + "*");
        if(keys != null && keys.size() > 0)
        {
            for(byte[] key : keys)
            {
                Session session = (Session) SerializeUtils.deserialize(redisManager.get(key));
                sessions.add(session);
            }
        }
        return sessions;
    }

    /**
     * 获得byte[]型的key
     * @param
     * @return
     */
    private byte[] getByteKey(Serializable sessionId){
        String preKey = this.keyPrefix + sessionId;
        return preKey.getBytes();
    }
}
